using System;
using System.Collections;
using System.Threading;
using Noea.TogSim.Model.Interfaces;
using Noea.TogSim.Model.Train.Engine;
using Noea.TogSim.Model.Train.LocoDriver;
using Noea.TogSim.Model.Tracks;
using Noea.TogSim.Model.Signal;

namespace Noea.TogSim.Model.Train
{
    public class TrainModel
    {
        ITrack _startTrack;
        ArrayList _trains;
        ArrayList _sensors;
        ITrainEngineDispatch _trainDispatcher;
        public TrainModel()
        {
            _trains = new ArrayList();
            _sensors = new ArrayList();
            _startTrack = GenerateTestRailroad();

            ITrainSet train;
            train = GenerateTestTrain(1, "Tog 1", 2, 500, _startTrack);
            _trains.Add(train);
            //train = GenerateTestTrain(3, "My Train", 4, 300, _startTrack.Next.Next.Next.Next.Next);
            //_trains.Add(train);
            //train = GenerateTestTrain(2, "Tog 2", 3, 10, _startTrack.Next.Next.Next.Next);
            //_trains.Add(train);

            /**** The dispatcher is instansed here *****/
            _trainDispatcher = new FixedTimeDispatch(_trains);

            //_trainDispatcher.Create();
        }
        private static ITrainSet GenerateTestTrain(int id, String desc, int numCars, float speed, ITrack startTrack)
        {
            ITrainSet train = new TrainSet(id, desc, startTrack);


            for (int i = 0; i < numCars; i++)
            {
                train.Add(new Car(i, "vogn " + i, 500, 8));
            }
            //*****  Loco driver here: LocoDriver_StPattern or LocoDriver_StMachSwitch
            /**** TrainDriver is instanced here *****/
            train.LocoDriver = new LocoDriver_StPattern(train);
       
            train.Engine = new TrainEngine(train, train.CurrentTrack);
            train.RequestedSpeed = speed;
            return train;
        }

        private ITrack GenerateTestRailroad()
        {

            SwitchTrack start = new SwitchTrack(100, false, 0, 0, null, null, SwitchTrack.Left);
            SwitchTrack swTrack2 = new SwitchTrack(200, false, 0, 0, null, null, SwitchTrack.Left);

            swTrack2.TrunkTrack = start;
            swTrack2.Next = start;
            start.TrunkTrack = swTrack2;
            start.Previous = swTrack2;

            ITrack prev = start;
            ITrack next = null;
            //SwitchTrack.Left er default SwitchTrack.Next
            for (int i = 0; i < 12; i++)
            {
                next = new SimpleTrack(i, false, 50, 30, null, prev);
                prev.Next = next;
                if (prev == start) start.LeftTrack = next;
                prev = next;
            }
            next.Next = swTrack2;
            swTrack2.Previous = next;
            swTrack2.LeftTrack = next;

            _startTrack = start;

            ITrack right = new SimpleTrack(12, false, 20, null, start);
            prev = right;
            for (int i = 13; i < 25; i++)
            {
                next = new SimpleTrack(i, false, 50, -30, null, prev);
                prev.Next = next;
                prev = next;
            }

            next.Next = swTrack2;
            swTrack2.RightTrack = next;

            start.RightTrack = right;

            ISignal signal = new SimpleSignal(1, SimpleSignal.Go);
            start.RightTrack.Next.Signals.Add(signal);
            SwitchSensor sensor = new SwitchSensor(1, false);
            _sensors.Add(sensor);
            SimpleSignalControl sc = new SimpleSignalControl((SimpleSignal)signal);
            sensor.OnChange += sc.ActOnSensor;
            signal = new OneViewSignal(2, SimpleSignal.Go, start.LeftTrack.Next.Next.Next);
            start.LeftTrack.Next.Next.Signals.Add(signal);

            sensor = new SwitchSensor(2, false);
            sc = new SimpleSignalControl((SimpleSignal)signal);
            sensor.OnChange += sc.ActOnSensor;
            start.LeftTrack.Next.Next.Next.Next.Sensors.Add(sensor);
            return start;
        }

        //private ITrack GenerateTestRailroad()
        //{
        //    SwitchTrack switch1 = new SwitchTrack(0, false, 50, 30, null, null, SwitchTrack.Left);
        //    SwitchTrack switch2 = new SwitchTrack(1, false, 50, -30, null, null, SwitchTrack.Left);

        //    SimpleTrack track1 = new SimpleTrack(2, false, 50, 30, null, null);
        //    SimpleTrack track2 = new SimpleTrack(3, false, 50, 30, null, null);

        //    SimpleTrack middleTrack = new SimpleTrack(4, false, 50, 0, null, null);

        //    middleTrack.Next = switch1.TrunkTrack;
        //    middleTrack.Previous = switch2.TrunkTrack;

        //    switch1.Previous = middleTrack;
            
        //    switch2.RightTrack = track1;
        //    switch1.RightTrack = track1;
        //    switch2.LeftTrack = track2;
        //    switch1.LeftTrack = track2;

        //    track1.Next = switch2.RightTrack;
        //    track1.Previous = switch1.RightTrack;
        //    track2.Next = switch1.LeftTrack;
        //    track2.Previous = switch2.LeftTrack;

        //    _startTrack = switch1;

            //SwitchTrack switch1 = new SwitchTrack(0, false, 50, 30, null, null, SwitchTrack.Left);
            //SwitchTrack switch2 = new SwitchTrack(11, false, 50, -30, null, null, SwitchTrack.Left);

            //ITrack prev = switch1;
            //ITrack next = null;

            //for (int i = 1; i < 10; i++)
            //{
            //    next = new SimpleTrack(i, false, 50, 30, null, prev);
            //    prev.Next = next;
            //    if (prev == switch1)
            //    {
            //        switch1.LeftTrack = next;
            //    }
            //    prev = next;
            //}

            //prev.Next = switch2;
            //prev.Next = switch2.RightTrack;
            //switch2.Previous = prev;
            //switch2.RightTrack = prev;

            //_startTrack = switch1;



            ////ITrack middleTrack = new SimpleTrack(11, false, 10, null, null);
            //ITrack middleTrack = new SimpleTrack(12, false, 10, 0, null, null);


            ////switch2.TrunkTrack = middleTrack;
            ////switch1.TrunkTrack = middleTrack;
            ////middleTrack.Next = switch1;
            ////middleTrack.Previous = switch2;

            //middleTrack.Previous = switch2.Previous;
            //switch2.TrunkTrack = middleTrack;
            //middleTrack.Next = switch1;
            //switch1.TrunkTrack = middleTrack;
            //switch1.Previous = middleTrack;
            //switch2.Next = middleTrack;


            //ITrack switch1Right = new SimpleTrack(13, false, 20, null, switch1);
            //ITrack switch2Right = new SimpleTrack(24, false, 20, null, switch2);

            //prev = switch1Right;

            //for (int i = 14; i < 23; i++)
            //{
            //    next = new SimpleTrack(i, false, 50, -30, null, prev);
            //    prev.Next = next;
            //    prev = next;
            //}


            ////SwitchTrack start = new SwitchTrack(0, false, 50, 30, null, null, SwitchTrack.Left);

            ////ITrack prev = start;
            ////ITrack next = null;
            ////for (int i = 1; i < 12; i++)
            ////{
            ////    next = new SimpleTrack(i, false, 50, 30, null, prev);
            ////    prev.Next = next;
            ////    if (prev == start) start.LeftTrack = next;
            ////    prev = next;
            ////}

            ////next.Next = start;
            ////start.Previous = next;
            ////start.TrunkTrack = next;

            ////_startTrack = start;

            ////ITrack right = new SimpleTrack(12, false, 20, null, start);
            ////prev = right;
            ////for (int i = 13; i < 20; i++)
            ////{
            ////    next = new SimpleTrack(i, false, 50, -30, null, prev);
            ////    prev.Next = next;
            ////    prev = next;
            ////}

            //prev = switch2Right;
            //switch1.RightTrack = switch1Right;
            //switch1.LeftTrack = switch1.Next;
            //switch2.RightTrack = switch2Right;


            ////start.RightTrack = right;
            ////start.LeftTrack = start.Next;

            //ISignal signal = new SimpleSignal(1, SimpleSignal.Go);
            //switch1.RightTrack.Next.Signals.Add(signal);
            //SwitchSensor sensor = new SwitchSensor(1, false);
            //_sensors.Add(sensor);
            //SimpleSignalControl sc = new SimpleSignalControl((SimpleSignal)signal);
            //sensor.OnChange += sc.ActOnSensor;
            //signal = new OneViewSignal(2, SimpleSignal.Go, switch1.LeftTrack.Next.Next.Next);
            //switch1.LeftTrack.Next.Next.Signals.Add(signal);

            //sensor = new SwitchSensor(2, false);
            //sc = new SimpleSignalControl((SimpleSignal)signal);
            //sensor.OnChange += sc.ActOnSensor;
            //switch1.LeftTrack.Next.Next.Next.Next.Sensors.Add(sensor);
        //    return switch1;
        //}

        public void Dispose()
        {
            foreach (ITrainSet t in TrainSets)
            {
                t.Engine.Stop();
            }
            _trainDispatcher.Dispose();
        }

        public void Start()
        {
            _trainDispatcher.Create();

            foreach (ITrainSet train in _trains)
            {
                train.LocoDriver.Go();
            }
        }
        public ITrack StartTrack
        {
            get { return _startTrack; }
        }
        public ArrayList TrainSets
        {
            get { return _trains; }
        }
        public ArrayList Sensors
        {
            get { return _sensors; }
        }

    }
}
